#pragma once
#include "message.hpp"
#include "net.hpp"
#include <unordered_map>
#include <functional>

namespace rpc
{
    // 建立消息类型与业务处理的关系
    class Callback
    {
    public:
        using ptr = std::shared_ptr<Callback>;
        virtual void onMessage(const BaseConnection::ptr &conn,  BaseMessage::ptr& msg) = 0;
    };

    template <typename T>
    class CallbackT : public Callback
    {
    public:
        using ptr = std::shared_ptr<CallbackT<T>>;
        using MessageCallback = std::function<void(const BaseConnection::ptr &conn, std::shared_ptr<T>&msg)>;
        CallbackT(const MessageCallback &handeler) : _handeler(handeler) {}
        void onMessage(const BaseConnection::ptr &conn, BaseMessage::ptr& msg) override
        {
            // 将message转换为T类型再来执行handeler函数
            auto type_msg = std::dynamic_pointer_cast<T>(msg); // 要接收
            delog("开始处理");
            _handeler(conn, type_msg);
            delog("处理完毕");
        }

    private:
        MessageCallback _handeler;
    };

    class dipatcher
    {
    public:
        using ptr = std::shared_ptr<dipatcher>;
        // 注册处理回调函数
        template <typename T>
        void rigisteHandler(MY_TYPE mytype, const typename CallbackT<T>::MessageCallback &handler)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto cb = std::make_shared<CallbackT<T>>(handler);
            delog("开始注册");
            _handlers.insert(std::make_pair(mytype, cb));
            delog("结束注册");
        }
        // 将_handler里面的业务处理函数进行调用
        void onMessage(const BaseConnection::ptr &conn,  BaseMessage::ptr &msg)
        {
            // 找到消息类型指向的消息处理函数，然后调用
            delog("消息开始处理");
            std::unique_lock<std::mutex> lock(_mutex);
            delog("开始查找回调函数");
            auto it = _handlers.find(msg->getMytype());
            if (it != _handlers.end())
            {
                delog("找到了处理方法");
                if(it->second)
                {
                    delog("开始处理");
                    return it->second->onMessage(conn, msg);
                    delog("结束处理");
                }
                delog("处理完成");
            }

            // 没找到是不可能的，直接断开连接
            errlog("未知消息类型：%d", (int)msg->getMytype());
            conn->disConnect();
        }

    private:
        std::unordered_map<MY_TYPE, Callback::ptr> _handlers;
        std::mutex _mutex;
    };
}
